<?php

namespace ApplicationsModule\GalleryModule;

use Nette\Object;
use Nette\Environment;
use Nette\Web\User;
use \InvalidArgumentException;

use Celebrio\FileSystem\FileSystemApi;
use Celebrio\FileSystem\FileNotFoundException;
use ApplicationsModule\GalleryModule\GallerySample;
use Celebrio\Core\ServiceProvider;
use Celebrio\Modules;
use ApplicationsModule\GalleryModule\LocalAlbum;
use ApplicationsModule\GalleryModule\Local;
use ApplicationsModule\GalleryModule\PicasaWeb;

class Gallery extends Object {
    
    private $service;
    private $fsApi;
    private $user;
    private $galleryPath;
    private $args = array();
    const REST_LOAD = '../api/rest/load?out=image&what=';
    const EMPTY_FOLDER = "/app/gallery/folder.png";
    
    public function __construct(User $user, $args = array()) {
        $this->user = $user;
        $this->galleryPath = "/usr/" . $this->getUserName() . "/gallery/";
        $this->args = $args;
        
       
    }
    
    private function getGalleryPath() {
        return $this->galleryPath;
    }
    
    /**
     * Find the first file in gallery and return as sample of gallery
     * 
     * @param string $url 
     * @return DataFile
     */
    public function getSample($url) {
        $remote = $this->getFileSystem();
        $gallery = $remote->load($url);
        $data = $gallery->getData();
        $firstSample = $data[0];
        $sample = $remote->load($firstSample->getUrl() . $firstSample->getName());
        
        return $sample;
        
    }
    
    /**
     * Find file(s) by the url of file(directory)
     * 
     * @param string $url identifier of file(s)
     * @return DataFile
     */
    public function getPhotos($galleryID, $userID, $serviceName) {
        $service = $this->getServiceImplementation($serviceName);
        $photos = $service->loadPhotosFromAlbum($galleryID, $userID);
        $result = array();
        foreach($photos as $album) {
            $sample = new GallerySample();
            $sample->setGalleryName($album->getName());
            $sample->setPictureUrl($album->getContentUrl());
            $sample->setGalleryID($album->getId());
            $sample->setUserID($album->getIdUser());
            $sample->setDescription($album->getDescription());
            $sample->setPictureThumbnail($album->getThumbnail());
            $sample->setServiceName($album->getService());
            
            $this->optimizeSample($sample);
            $result[] = $sample;
        }
        /*$remote = $this->getFileSystem();
        $photos = $remote->load($this->getGalleryPath() . $galleryName);*/
        return $result;
    }
    
    /**
     * Gathering photos from different storages (picasa, local at the moment)
     * 
     * @return array of GallerySample(s) (hope so)
     */
    public function getSamples($services) {
        if($services === null) {
            throw new InvalidArgumentException("No service given");
        }
        $albums = array();
        foreach($services as $service) {
            $loaded_albums = $service->loadAlbums();
            //TODO: refactor to function
            if($loaded_albums !== null) {
                foreach($loaded_albums as $album) {
                    $albums[] = $album;
                }
            }
            
        }
        $samples = array();
        foreach($albums as $album) {
            $sample = new GallerySample();
            $sample->setGalleryName($album->getName());
            $sample->setPictureUrl($album->getContentUrl());
            $sample->setGalleryID($album->getId());
            $sample->setUserID($album->getIdUser());
            $sample->setDescription($album->getDescription());
            $sample->setPictureThumbnail($album->getThumbnail());
            $sample->setServiceName($album->getService());
            
            $this->optimizeSample($sample);
            $samples[] = $sample;
        }
        
        return $samples;
    
    }
    
    public function createAlbum($name, $service = null) {
        if($service != null) {
            $services = $this->getServiceImplementation($service);
        } else {
            $services = ServiceProvider::getAllServices(Modules::GALLERY_DRIVERS);
        }
        foreach($services as $serviceImp) {
            $serviceImp->createAlbum($name);
        }
    }


    private function createLocalAlbum($pictureUrl, $galleryName) {
        $localAlbum = new LocalAlbum();
        $localAlbum->setContentUrl(self::REST_LOAD . $pictureUrl);
        $localAlbum->setThumbnail($pictureUrl);
        $localAlbum->setName($galleryName);
        return $localAlbum;
    }
    
    function createGallerySample($pictureUrl, $galleryName) {
        $sample = new GallerySample();
        $sample->setPictureUrl($pictureUrl);
        $sample->setGalleryName($galleryName);
        $this->optimizeSample($sample);
        return $sample;
    }
    
    function optimizeSample(GallerySample $sample) {
        $sample->setHeight(200);
    }
    
    
    /**
     * Find all galleries
     * 
     * DEPRACATED??
     * 
     * @return array of DataFiles
     */
    public function getGalleries() {
        $remote = $this->getFileSystem();
        $galleries = $remote->load($this->galleryPath)->getData();
        $result = array();
        foreach($galleries as $gallery) {
            $result[] = $gallery;
        }
        return $result;
        
    }
    
    
    
    /**
     * 
     * 
     * @return type 
     */
    public function makeGallery($service, $name) {
        $serviceImpl = $this->getServiceImplementation($service);
        $serviceImpl->setUser($this->getUser());
        $serviceImpl->createAlbum($name);
    }
    
    public function savePhoto($albumName, $photoName, $data, $mimeType, $service = null) {
        if(!empty($service)) {
            $this->setService($service);
        }
        $serviceImpl = $this->getService();
        $serviceImpl->savePhoto($albumName, $photoName, $data, $mimeType);
        
    }
    
    
    public function getGalleryNames($services) {
        if($services === null)
            throw new InvalidArgumentException("No service given");
        $names = array();
        foreach($services as $service) {
            $names_temp = $service->getGalleryNames();
            if($names_temp !== null) {
                foreach($names_temp as $name) {
                    $names[$name["id"] . "," . $service::NAME] = $name["name"];
                }
            }
        }
        return $names;
    }
    
    public static function getAvailableServicesNames() {
        $services = ServiceProvider::getAllServiceNames(Modules::GALLERY_DRIVERS);
    }
    
    public function getAvailableServices() {
        //TODO: make this more general
        $services = ServiceProvider::getAllServices(Modules::GALLERY_DRIVERS);
        //temporary:
//        $services = array(
//            //$picasa = new PicasaWeb(),
//            $local = new Local()
//        );
        
        $available = array();
        $user = $this->getUser();
        foreach($services as $service) {
            $service->setUser($user);
            if($service->checkAvailability()) {
                $available[] = $service;
            }
        }
        return $available;
    }
    
    private function getServiceImplementation($service) {
        //TODO: Tohle se musi udelat hezke
        if($service === "picasa") {
            return new PicasaWeb();
        } elseif($service === "local") {
            return new Local();
        } else {
            throw new \InvalidArgumentException("Unknown service " . $service);
        }
    }
    
    public function setService($service) {
        $this->service = $this->getServiceImplementation($service);
        $this->service->setUser($this->getUser());
    }
    
    private function getService() {
        if(empty($this->service)) {
            $this->setService($this->getServiceImplementation("picasa"));
        }
        return $this->service;
    }
    
    /**
     * This should be moved to LOCAL!
     * 
     * @return type 
     */
    private function getUserName() {
        return $this->user->getIdentity()->name;
    }
    
    
    /**
     * This should be move to LOCAL!
     * 
     * @return type 
     */
    private function getUser() {
        return $this->user;
    }
}